#include "duktape.h"
#include "pmd.h"
#include "utils.h"
#include "log.h"
#include "on_msg.h"

typedef struct PmdEventCallbackParam_t{
    Msg msg;
    PmdEventParam param;
}PmdEventCallbackParam;

static void* pmd_evt_to_task = 0;
static void pmd_evt_callback(PmdEventParam* p,duk_context* ctx){
    if(!pmd_evt_to_task){
        ERROR("pmd_evt_to_task == 0");
        return ;
    }
    PmdEventCallbackParam* param = (PmdEventCallbackParam*)malloc(sizeof(PmdEventCallbackParam));
    if(!param){
        ERROR("alloc PmdEventCallbackParam failed");
        return ;
    }
    param->msg.id = MSG_PMD_EVENT_CB;
    param->msg.args = 0;
    memcpy(&param->param,p,sizeof(PmdEventParam));
    platform_send_msg(pmd_evt_to_task,param);
}

static int on_pmd_evt_callback_msg(duk_context* ctx,PmdEventCallbackParam* pMsg){
    duk_peval_string(ctx,"iot.pmd.onMsg");//[onMsg]
 
    if(duk_is_function(ctx,-1)){
        duk_push_int(ctx,pMsg->param.evtId);//[onMsg,evtId]
        duk_push_object(ctx);//[onMsg,evtId,object]
        switch (pMsg->param.evtId)
        {
        case CHR_PRESENT_IND:{
            duk_push_boolean(ctx,pMsg->param.ChargerPresent.present);//[onMsg,evtId,object,ChargerPresent]
            duk_put_prop_string(ctx,-2,"ChargerPresent");//[onMsg,evtId,object]
        }break;
        case BAT_LEVEL_IND:
        case BAT_CHARGING:{
            duk_push_int(ctx,pMsg->param.chargingind.batteryLevel);
            duk_put_prop_string(ctx,-2,"batteryLevel");
        }break;
        case POWERON_ON_IND:{
            duk_push_int(ctx,pMsg->param.poweronind.powerOnReason);
            duk_put_prop_string(ctx,-2,"powerOnReason");
        }break;
        default:
            break;
        }
        duk_pcall(ctx,2);//[ret]
        duk_pop(ctx);
    }
    return 0;
}
//[mode,cfg]
static duk_ret_t init(duk_context *ctx) {
    int mode = duk_get_int_default(ctx,0,0);
    if(!duk_is_object(ctx,1)){
        duk_remove(ctx,1);
        duk_push_object(ctx);
    }
    pmd_evt_to_task = platform_current_task();

    PmdConfig cfg;    
    duk_get_prop_string(ctx,1,"batdetectEnable");//[mode,cfg,batdetectEnable]
    cfg.batdetectEnable = duk_get_boolean_default(ctx,-1,1);
    duk_pop(ctx);//[mode,cfg]

    duk_get_prop_string(ctx,1,"tempdetectEnable");//[mode,cfg,tempdetectEnable]
    cfg.tempdetectEnable = duk_get_boolean_default(ctx,-1,0);
    duk_pop(ctx);//[mode,cfg]

    duk_get_prop_string(ctx,1,"templowLevel");//[mode,cfg,templowLevel]
    cfg.templowLevel = duk_get_int_default(ctx,-1,0);
    duk_pop(ctx);//[mode,cfg]

    duk_get_prop_string(ctx,1,"temphighLevel");//[mode,cfg,temphighLevel]
    cfg.temphighLevel = duk_get_int_default(ctx,-1,0);
    duk_pop(ctx);//[mode,cfg]

    duk_get_prop_string(ctx,1,"batLevelEnable");//[mode,cfg,batLevelEnable]
    cfg.batLevelEnable = duk_get_int_default(ctx,-1,0);
    duk_pop(ctx);//[mode,cfg]

    if(!platform_pmd_init(mode,&cfg,pmd_evt_callback,ctx)){
        //ok
        duk_push_true(ctx);
    }else{
        duk_push_false(ctx);
    }
    return 1;
}
//[simStartUpMode,nwStartupMode]
static duk_ret_t powerOn(duk_context *ctx) {
    int simStartUpMode = duk_get_int_default(ctx,0,0);
    int nwStartupMode =  duk_get_int_default(ctx,1,0);
    if(!platform_pmd_poweron_system(simStartUpMode,nwStartupMode)){
        duk_push_true(ctx);
    }else{
        duk_push_false(ctx);
    }
    return 1;
}
static duk_ret_t powerOff(duk_context *ctx) {
    if(!platform_pmd_poweroff_system()){
        duk_push_true(ctx);
    }else{
        duk_push_false(ctx);
    }
    return 1;
}
static duk_ret_t enterDeepSleep(duk_context *ctx) {
    duk_bool_t enter = duk_get_boolean_default(ctx,0,0);
    if(!platform_pmd_enter_deepsleep(enter)){
        duk_push_true(ctx);
    }else{
        duk_push_false(ctx);
    }
    return 1;
}
static duk_ret_t getBatteryInfo(duk_context *ctx) {
    BatteryInfo batteryinfo = {0};
    if(platform_get_battery_info(&batteryinfo)){
        duk_push_undefined(ctx);
    }else{
        duk_push_bare_object(ctx);
        duk_push_int(ctx,batteryinfo.battStatus);
        duk_put_prop_string(ctx,-2,"battStatus");
        duk_push_int(ctx,batteryinfo.battVolt);
        duk_put_prop_string(ctx,-2,"battVolt");
        duk_push_int(ctx,batteryinfo.battLevel);
        duk_put_prop_string(ctx,-2,"battLevel");
        duk_push_int(ctx,batteryinfo.chargerStatus);
        duk_put_prop_string(ctx,-2,"chargerStatus");
        duk_push_int(ctx,batteryinfo.chargeState);
        duk_put_prop_string(ctx,-2,"chargeState");
    }
    return 1;
}
static duk_function_list_entry module_funcs[] = {
    {"init",init,2},
    {"powerOn",powerOn,2},
    {"powerOff",powerOff,1},
    {"enterDeepSleep",enterDeepSleep,1},
    {"getBatteryInfo",getBatteryInfo,0},
    {0/*name*/,0/*c function*/,0 /*nargs*/}
};
int pwd_init(duk_context* ctx){
    register_msg_handler(MSG_PMD_EVENT_CB,on_pmd_evt_callback_msg);
    register_module_funcs(ctx,"iot.pmd",module_funcs);
    return 0;
}